package org.bsc.vfs.gae;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringWriter;

import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileType;

import com.newatlanta.commons.vfs.provider.gae.GaeVFS;
import com.sun.jersey.multipart.FormDataBodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;

/**
 * 
 * @author softphone
 *
 */
@Path( "vfs/{path}")
public class VFSRestService {
	final Log logger = org.apache.commons.logging.LogFactory.getLog(getClass());

	@Context ServletContext servletContext;
	
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public Response list( @PathParam("path") String path) {
		
		if( path == null) {
			return Response.status(Status.BAD_REQUEST).entity("path is null!").build();
		}
		
		if( !path.endsWith("/")) {
			path = path.concat("/");
		}

		try {

        	final String fileToResolve = String.format("gae://%s", path);
        	
        	logger.info( String.format("resolve file [%s]", fileToResolve));
        	
            final FileObject fileObject = GaeVFS.resolveFile( fileToResolve );

            if( !fileObject.exists()) {
    			return Response.status(Status.BAD_REQUEST).entity("path doesn't exist!").build();
            	
            }
            if( fileObject.getType() != FileType.FOLDER ) {
    			return Response.status(Status.BAD_REQUEST).entity("path is not a folder!").build();
            	
            }
      
            final FileObject[] children = fileObject.getChildren();
            
            if( children != null && children.length > 0) {
            	
            	java.util.Properties p = new java.util.Properties();
            	
            	for( FileObject f : children ) {
            	
            		p.setProperty(f.getName().getBaseName(), f.getName().getPath());
            		
            	}
            	
            	final StringWriter sw = new StringWriter(4096);
            	
            	p.store(sw, String.format("list of folder %s", path));
            	
            	sw.close();
            	
            	return Response.ok().entity(sw.toString()).build();
            	
            }
            
		}
		catch( Exception e ) {
			logger.error( "error reading folder content", e );
			return Response.serverError().entity(e.getMessage()).build();
		}
		
		return Response.ok().build();
		
	}
	
	@POST
	@Consumes(MediaType.MULTIPART_FORM_DATA)
	public Response post(@PathParam("path") String path, FormDataMultiPart part) throws IOException {

		if( path == null) {
			return Response.status(Status.BAD_REQUEST).entity("path is null!").build();
		}
		

        int blockSize = 0;
		
		//FormDataBodyPart fieldPath	= part.getField("path");
		FormDataBodyPart fieldBlockSize = part.getField("blocksize");
		FormDataBodyPart fieldFile		= part.getField("file");

		if( fieldFile == null ) {
			return Response.status(Status.BAD_REQUEST).entity("file is null!").build();			
		}
		
		if( !path.endsWith("/")) {
			path = path.concat("/");
		}
		
		if( fieldBlockSize != null ) {
			String value = fieldBlockSize.getValue();
			if( value != null ) {
				
				try {
					blockSize = Integer.parseInt(value);					
				} catch (Exception e) {
					logger.warn(String.format("blocksize param is not a valid number! [%s]", value));
				}
			}
			
		}

		try {

        	final String fileToResolve = String.format("gae://%s%s", path, fieldFile.getFormDataContentDisposition().getFileName());
        	
        	logger.info( String.format("resolve file [%s]", fileToResolve));
        	
            final FileObject fileObject = GaeVFS.resolveFile( fileToResolve );
            
            if ( blockSize > 0 ) {
                GaeVFS.setBlockSize( fileObject, blockSize );
            }
            
			java.io.InputStream is = fieldFile.getValueAs(java.io.InputStream.class);
			
            copyAndClose( is, fileObject.getContent().getOutputStream() );
						
		}
		catch( Exception e ) {
			logger.error( "error get field as InputStream", e );
			return Response.serverError().entity(e.getMessage()).build();
		}
		finally {
            GaeVFS.clearFilesCache();	
		}
		
		return Response.ok().build();
	}

    /**
     * Copy the InputStream to the OutputStream then close them both.
     */
    private void copyAndClose( InputStream in, OutputStream out ) throws IOException {
        IOUtils.copy( in, out );
        out.close();
        in.close();
    }

	
}
